Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Node / ReticulumProjects / MeshChatX.git / files / tests / backend / test_docs_manager.py

Displaying Raw • Download


tests/backend/test_docs_manager.py fda9187e95d8b9cc8373c1de23cefce6928c241d (fda9187e) Text, 6.67 KB

Tff7b72import T7ee787os
Tff7b72import T7ee787shutil
Tff7b72import T7ee787zipfile
Tff7b72from T7ee787unittestT7ee787.T7ee787mock Tff7b72import Te6edf3MagicMockTb4b4b4, Te6edf3patch

Tff7b72import T7ee787pytest
Tff7b72from T7ee787hypothesis Tff7b72import Te6edf3HealthCheckTb4b4b4, Te6edf3givenTb4b4b4, Te6edf3settings
Tff7b72from T7ee787hypothesis Tff7b72import Te6edf3strategies Tff7b72as Te6edf3st

Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787docs_manager Tff7b72import Te6edf3DocsManager


Tf0883e@pytestTff7b72.Td2a8fffixture
Tff7b72def Td2a8fftemp_dirsTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4:
Te6edf3public_dir Tff7b72= Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffpublicTa5d6ff"
Te6edf3public_dirTff7b72.Td2a8ffmkdirTb4b4b4(Tb4b4b4)
Te6edf3docs_dir Tff7b72= Te6edf3public_dir Tff7b72/ Ta5d6ff"Ta5d6ffreticulum-docsTa5d6ff"
Te6edf3docs_dirTff7b72.Td2a8ffmkdirTb4b4b4(Tb4b4b4)
Tff7b72return Tffa657strTb4b4b4(Te6edf3public_dirTb4b4b4)Tb4b4b4, Tffa657strTb4b4b4(Te6edf3docs_dirTb4b4b4)


Tf0883e@pytestTff7b72.Td2a8fffixture
Tff7b72def Td2a8ffdocs_managerTb4b4b4(Te6edf3temp_dirsTb4b4b4)Tb4b4b4:
Te6edf3public_dirTb4b4b4, Te6edf3_ Tff7b72= Te6edf3temp_dirs
Te6edf3config Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)
Te6edf3configTff7b72.Td2a8ffdocs_downloadedTff7b72.Td2a8ffgetTff7b72.Td2a8ffreturn_value Tff7b72= Tff7b72False
Tff7b72return Te6edf3DocsManagerTb4b4b4(Te6edf3configTb4b4b4, Te6edf3public_dirTb4b4b4)


Tff7b72def Td2a8fftest_docs_manager_initializationTb4b4b4(Te6edf3docs_managerTb4b4b4, Te6edf3temp_dirsTb4b4b4)Tb4b4b4:
Te6edf3_Tb4b4b4, Te6edf3docs_dir Tff7b72= Te6edf3temp_dirs
Tff7b72assert Te6edf3docs_managerTff7b72.Td2a8ffdocs_dir Tff7b72== Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3docs_dirTb4b4b4, Ta5d6ff"Ta5d6ffcurrentTa5d6ff"Tb4b4b4)
Tff7b72assert Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3docs_dirTb4b4b4)
Tff7b72assert Te6edf3docs_managerTff7b72.Td2a8ffdownload_status Tff7b72== Ta5d6ff"Ta5d6ffidleTa5d6ff"


Tff7b72def Td2a8fftest_docs_manager_storage_dir_fallbackTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4:
Te6edf3public_dir Tff7b72= Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffpublicTa5d6ff"
Te6edf3public_dirTff7b72.Td2a8ffmkdirTb4b4b4(Tb4b4b4)
Te6edf3storage_dir Tff7b72= Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffstorageTa5d6ff"
Te6edf3storage_dirTff7b72.Td2a8ffmkdirTb4b4b4(Tb4b4b4)

Te6edf3config Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)
T8b949e# If storage_dir is provided, it should be used for docs
Te6edf3dm Tff7b72= Te6edf3DocsManagerTb4b4b4(Te6edf3configTb4b4b4, Tffa657strTb4b4b4(Te6edf3public_dirTb4b4b4)Tb4b4b4, Te6edf3storage_dirTff7b72=Tffa657strTb4b4b4(Te6edf3storage_dirTb4b4b4)Tb4b4b4)

Tff7b72assert Te6edf3dmTff7b72.Td2a8ffdocs_dir Tff7b72== Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tffa657strTb4b4b4(Te6edf3storage_dirTb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffreticulum-docsTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffcurrentTa5d6ff"Tb4b4b4)
Tff7b72assert Te6edf3dmTff7b72.Td2a8ffmeshchatx_docs_dir Tff7b72== Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tffa657strTb4b4b4(Te6edf3storage_dirTb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffmeshchatx-docsTa5d6ff"Tb4b4b4)
T8b949e# The 'current' directory may not exist if there are no versions, but the base dir should exist
Tff7b72assert Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3dmTff7b72.Td2a8ffdocs_base_dirTb4b4b4)
Tff7b72assert Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3dmTff7b72.Td2a8ffmeshchatx_docs_dirTb4b4b4)


Tff7b72def Td2a8fftest_docs_manager_readonly_public_dir_handlingTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4:
T8b949e# This test simulates a read-only public dir without storage_dir
Te6edf3public_dir Tff7b72= Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffreadonly_publicTa5d6ff"
Te6edf3public_dirTff7b72.Td2a8ffmkdirTb4b4b4(Tb4b4b4)

T8b949e# Make it read-only
Te6edf3osTff7b72.Td2a8ffchmodTb4b4b4(Te6edf3public_dirTb4b4b4, T79c0ff0o555Tb4b4b4)

Te6edf3config Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)
T8b949e# Mock os.makedirs to force it to fail, as some environments (like CI running as root)
T8b949e# might still allow writing to 555 directories.
Tff7b72with Te6edf3patchTb4b4b4(Ta5d6ff"Ta5d6ffos.makedirsTa5d6ff"Tb4b4b4, Te6edf3side_effectTff7b72=Tf85149OSErrorTb4b4b4(Ta5d6ff"Ta5d6ffRead-only file systemTa5d6ff"Tb4b4b4)Tb4b4b4)Tb4b4b4:
Te6edf3dm Tff7b72= Te6edf3DocsManagerTb4b4b4(Te6edf3configTb4b4b4, Tffa657strTb4b4b4(Te6edf3public_dirTb4b4b4)Tb4b4b4)
Tff7b72assert Te6edf3dmTff7b72.Td2a8fflast_error Tff7b72is Tff7b72not Tff7b72None
Tff7b72assert Tb4b4b4(
Ta5d6ff"Ta5d6ffRead-only file systemTa5d6ff" Tff7b72in Te6edf3dmTff7b72.Td2a8fflast_error
Tff7b72or Ta5d6ff"Ta5d6ffPermission deniedTa5d6ff" Tff7b72in Te6edf3dmTff7b72.Td2a8fflast_error
Tb4b4b4)

T8b949e# Restore permissions for cleanup
Te6edf3osTff7b72.Td2a8ffchmodTb4b4b4(Te6edf3public_dirTb4b4b4, T79c0ff0o755Tb4b4b4)


Tff7b72def Td2a8fftest_has_docsTb4b4b4(Te6edf3docs_managerTb4b4b4, Te6edf3temp_dirsTb4b4b4)Tb4b4b4:
Te6edf3_Tb4b4b4, Te6edf3docs_dir Tff7b72= Te6edf3temp_dirs
Tff7b72assert Te6edf3docs_managerTff7b72.Td2a8ffhas_docsTb4b4b4(Tb4b4b4) Tff7b72is Tff7b72False

Te6edf3current_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3docs_dirTb4b4b4, Ta5d6ff"Ta5d6ffcurrentTa5d6ff"Tb4b4b4)
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Te6edf3current_dirTb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)
Te6edf3index_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3current_dirTb4b4b4, Ta5d6ff"Ta5d6ffindex.htmlTa5d6ff"Tb4b4b4)
Tff7b72with Tffa657openTb4b4b4(Te6edf3index_pathTb4b4b4, Ta5d6ff"Ta5d6ffwTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3fTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ff<html></html>Ta5d6ff"Tb4b4b4)

Tff7b72assert Te6edf3docs_managerTff7b72.Td2a8ffhas_docsTb4b4b4(Tb4b4b4) Tff7b72is Tff7b72True


Tff7b72def Td2a8fftest_get_statusTb4b4b4(Te6edf3docs_managerTb4b4b4)Tb4b4b4:
Te6edf3status Tff7b72= Te6edf3docs_managerTff7b72.Td2a8ffget_statusTb4b4b4(Tb4b4b4)
Tff7b72assert Te6edf3statusTb4b4b4[Ta5d6ff"Ta5d6ffstatusTa5d6ff"Tb4b4b4] Tff7b72== Ta5d6ff"Ta5d6ffidleTa5d6ff"
Tff7b72assert Te6edf3statusTb4b4b4[Ta5d6ff"Ta5d6ffprogressTa5d6ff"Tb4b4b4] Tff7b72== T79c0ff0
Tff7b72assert Te6edf3statusTb4b4b4[Ta5d6ff"Ta5d6ffhas_docsTa5d6ff"Tb4b4b4] Tff7b72is Tff7b72False


Tf0883e@patchTb4b4b4(Ta5d6ff"Ta5d6ffrequests.getTa5d6ff"Tb4b4b4)
Tff7b72def Td2a8fftest_download_task_successTb4b4b4(Te6edf3mock_getTb4b4b4, Te6edf3docs_managerTb4b4b4, Te6edf3temp_dirsTb4b4b4)Tb4b4b4:
Te6edf3public_dirTb4b4b4, Te6edf3docs_dir Tff7b72= Te6edf3temp_dirs

T8b949e# Mock response
Te6edf3mock_response Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)
Te6edf3mock_responseTff7b72.Td2a8ffheaders Tff7b72= Tb4b4b4{Ta5d6ff"Ta5d6ffcontent-lengthTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ff100Ta5d6ff"Tb4b4b4}
Te6edf3mock_responseTff7b72.Td2a8ffiter_contentTff7b72.Td2a8ffreturn_value Tff7b72= Tb4b4b4[Ta5d6ffbTa5d6ff"Ta5d6ffdataTa5d6ff" Tff7b72* T79c0ff25Tb4b4b4]
Te6edf3mock_getTff7b72.Td2a8ffreturn_value Tff7b72= Te6edf3mock_response

T8b949e# Mock extract_docs to avoid real zip issues
Tff7b72with Te6edf3patchTff7b72.Td2a8ffobjectTb4b4b4(Te6edf3docs_managerTb4b4b4, Ta5d6ff"Ta5d6ff_extract_docsTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3mock_extractTb4b4b4:
Te6edf3docs_managerTff7b72.Td2a8ff_download_taskTb4b4b4(Tb4b4b4)

Tff7b72assert Te6edf3docs_managerTff7b72.Td2a8ffdownload_status Tff7b72== Ta5d6ff"Ta5d6ffcompletedTa5d6ff"
Tff7b72assert Te6edf3mock_extractTff7b72.Td2a8ffcalled
Te6edf3zip_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3docs_dirTb4b4b4, Ta5d6ff"Ta5d6ffwebsite.zipTa5d6ff"Tb4b4b4)
Te6edf3call_args Tff7b72= Te6edf3mock_extractTff7b72.Td2a8ffcall_args
Tff7b72assert Te6edf3call_argsTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4] Tff7b72== Te6edf3zip_path
Tff7b72assert Te6edf3call_argsTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff1Tb4b4b4]Tff7b72.Td2a8ffstartswithTb4b4b4(Ta5d6ff"Ta5d6ffgit-Ta5d6ff"Tb4b4b4)


Tf0883e@patchTb4b4b4(Ta5d6ff"Ta5d6ffrequests.getTa5d6ff"Tb4b4b4)
Tff7b72def Td2a8fftest_download_task_failureTb4b4b4(Te6edf3mock_getTb4b4b4, Te6edf3docs_managerTb4b4b4)Tb4b4b4:
Te6edf3mock_getTff7b72.Td2a8ffside_effect Tff7b72= Tf85149ExceptionTb4b4b4(Ta5d6ff"Ta5d6ffDownload failedTa5d6ff"Tb4b4b4)

Te6edf3docs_managerTff7b72.Td2a8ff_download_taskTb4b4b4(Tb4b4b4)

Tff7b72assert Te6edf3docs_managerTff7b72.Td2a8ffdownload_status Tff7b72== Ta5d6ff"Ta5d6fferrorTa5d6ff"
Tff7b72assert Te6edf3docs_managerTff7b72.Td2a8fflast_error Tff7b72== Ta5d6ff"Ta5d6ffDownload failedTa5d6ff"


Tff7b72def Td2a8ffcreate_mock_zipTb4b4b4(Te6edf3zip_pathTb4b4b4, Te6edf3file_listTb4b4b4)Tb4b4b4:
Tff7b72with Te6edf3zipfileTff7b72.Td2a8ffZipFileTb4b4b4(Te6edf3zip_pathTb4b4b4, Ta5d6ff"Ta5d6ffwTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3zfTb4b4b4:
Tff7b72for Te6edf3file_path Tff7b72in Te6edf3file_listTb4b4b4:
Te6edf3zfTff7b72.Td2a8ffwritestrTb4b4b4(Te6edf3file_pathTb4b4b4, Ta5d6ff"Ta5d6fftest contentTa5d6ff"Tb4b4b4)


Tf0883e@settingsTb4b4b4(
Te6edf3deadlineTff7b72=Tff7b72NoneTb4b4b4,
Te6edf3suppress_health_checkTff7b72=Tb4b4b4[
Te6edf3HealthCheckTff7b72.Td2a8fffilter_too_muchTb4b4b4,
Te6edf3HealthCheckTff7b72.Td2a8fffunction_scoped_fixtureTb4b4b4,
Tb4b4b4]Tb4b4b4,
Tb4b4b4)
Tf0883e@givenTb4b4b4(
Te6edf3root_folder_nameTff7b72=Te6edf3stTff7b72.Td2a8fftextTb4b4b4(Te6edf3min_sizeTff7b72=T79c0ff1Tb4b4b4, Te6edf3max_sizeTff7b72=T79c0ff50Tb4b4b4)Tff7b72.Td2a8fffilterTb4b4b4(
Tff7b72lambda Te6edf3xTb4b4b4: Ta5d6ff"Ta5d6ff/Ta5d6ff" Tff7b72not Tff7b72in Te6edf3x Tff7b72and Te6edf3x Tff7b72not Tff7b72in Tb4b4b4[Ta5d6ff"Ta5d6ff.Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff..Ta5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Te6edf3docs_fileTff7b72=Te6edf3stTff7b72.Td2a8fftextTb4b4b4(Te6edf3min_sizeTff7b72=T79c0ff1Tb4b4b4, Te6edf3max_sizeTff7b72=T79c0ff50Tb4b4b4)Tff7b72.Td2a8fffilterTb4b4b4(Tff7b72lambda Te6edf3xTb4b4b4: Ta5d6ff"Ta5d6ff/Ta5d6ff" Tff7b72not Tff7b72in Te6edf3xTb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72def Td2a8fftest_extract_docs_fuzzingTb4b4b4(Te6edf3docs_managerTb4b4b4, Te6edf3temp_dirsTb4b4b4, Te6edf3root_folder_nameTb4b4b4, Te6edf3docs_fileTb4b4b4)Tb4b4b4:
Te6edf3public_dirTb4b4b4, Te6edf3docs_dir Tff7b72= Te6edf3temp_dirs
Te6edf3zip_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3docs_dirTb4b4b4, Ta5d6ff"Ta5d6fftest.zipTa5d6ff"Tb4b4b4)

T8b949e# Create a zip structure similar to what DocsManager expects
T8b949e# reticulum_website-main/docs/some_file.html
Te6edf3zip_files Tff7b72= Tb4b4b4[
Ta5d6fffTa5d6ff"Tffd700{Te6edf3root_folder_nameTffd700}Ta5d6ff/Ta5d6ff"Tb4b4b4,
Ta5d6fffTa5d6ff"Tffd700{Te6edf3root_folder_nameTffd700}Ta5d6ff/docs/Ta5d6ff"Tb4b4b4,
Ta5d6fffTa5d6ff"Tffd700{Te6edf3root_folder_nameTffd700}Ta5d6ff/docs/Tffd700{Te6edf3docs_fileTffd700}Ta5d6ff"Tb4b4b4,
Tb4b4b4]

Te6edf3create_mock_zipTb4b4b4(Te6edf3zip_pathTb4b4b4, Te6edf3zip_filesTb4b4b4)

Tff7b72tryTb4b4b4:
Te6edf3docs_managerTff7b72.Td2a8ff_extract_docsTb4b4b4(Te6edf3zip_pathTb4b4b4)
T8b949e# Check if the file was extracted to the right place
Te6edf3extracted_file Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3docs_dirTb4b4b4, Te6edf3docs_fileTb4b4b4)
Tff7b72assert Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3extracted_fileTb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
T8b949e# If it's a known zip error or something, we can decide if it's a failure
T8b949e# But for these valid-ish paths, it should work.
Tff7b72pass
Tff7b72finallyTb4b4b4:
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3zip_pathTb4b4b4)Tb4b4b4:
Te6edf3osTff7b72.Td2a8ffremoveTb4b4b4(Te6edf3zip_pathTb4b4b4)
T8b949e# Clean up extracted files for next run
Tff7b72for Te6edf3item Tff7b72in Te6edf3osTff7b72.Td2a8fflistdirTb4b4b4(Te6edf3docs_dirTb4b4b4)Tb4b4b4:
Te6edf3item_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3docs_dirTb4b4b4, Te6edf3itemTb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Te6edf3item_pathTb4b4b4)Tb4b4b4:
Te6edf3shutilTff7b72.Td2a8ffrmtreeTb4b4b4(Te6edf3item_pathTb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3osTff7b72.Td2a8ffremoveTb4b4b4(Te6edf3item_pathTb4b4b4)


Tff7b72def Td2a8fftest_extract_docs_malformed_zipTb4b4b4(Te6edf3docs_managerTb4b4b4, Te6edf3temp_dirsTb4b4b4)Tb4b4b4:
Te6edf3public_dirTb4b4b4, Te6edf3docs_dir Tff7b72= Te6edf3temp_dirs
Te6edf3zip_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3docs_dirTb4b4b4, Ta5d6ff"Ta5d6ffmalformed.zipTa5d6ff"Tb4b4b4)

T8b949e# 1. Zip with no folders at all
Te6edf3create_mock_zipTb4b4b4(Te6edf3zip_pathTb4b4b4, Tb4b4b4[Ta5d6ff"Ta5d6fffile_at_root.txtTa5d6ff"Tb4b4b4]Tb4b4b4)
Tff7b72tryTb4b4b4:
T8b949e# This might fail with IndexError at namelist()[0].split('/')[0] if no slash
Te6edf3docs_managerTff7b72.Td2a8ff_extract_docsTb4b4b4(Te6edf3zip_pathTb4b4b4)
Tff7b72except Tb4b4b4(Tf85149IndexErrorTb4b4b4, Tf85149ExceptionTb4b4b4)Tb4b4b4:
Tff7b72pass T8b949e# Expected or at least handled by not crashing the whole app
Tff7b72finallyTb4b4b4:
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3zip_pathTb4b4b4)Tb4b4b4:
Te6edf3osTff7b72.Td2a8ffremoveTb4b4b4(Te6edf3zip_pathTb4b4b4)

T8b949e# 2. Zip with different structure
Te6edf3create_mock_zipTb4b4b4(Te6edf3zip_pathTb4b4b4, Tb4b4b4[Ta5d6ff"Ta5d6ffroot/not_docs/file.txtTa5d6ff"Tb4b4b4]Tb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3docs_managerTff7b72.Td2a8ff_extract_docsTb4b4b4(Te6edf3zip_pathTb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72pass
Tff7b72finallyTb4b4b4:
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3zip_pathTb4b4b4)Tb4b4b4:
Te6edf3osTff7b72.Td2a8ffremoveTb4b4b4(Te6edf3zip_pathTb4b4b4)


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────